package hn.cch.spring_boot_security_rest.filter;


import hn.cch.spring_boot_security_rest.constant.SystemInfo;
import hn.cch.spring_boot_security_rest.wrapper.ApiRequestWrapper;
import hn.cch.spring_boot_security_rest.wrapper.ApiResponseWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.http.MediaType;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

/**
 * 过滤器
 */
@WebFilter(filterName = "apiFilter", urlPatterns = "/api/*")
public class ApiFilter extends OncePerRequestFilter {

    private static Logger logger = LoggerFactory.getLogger(ApiFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

        try {
            long start = System.currentTimeMillis(); // 请求进入时间
            ApiRequestWrapper requestWrapper = new ApiRequestWrapper(httpServletRequest);
            ApiResponseWrapper responseWrapper = new ApiResponseWrapper(httpServletResponse);
            String requestId = requestWrapper.getHeader(SystemInfo.REQUEST_ID);
            if (requestId == null) {
                requestId = UUID.randomUUID().toString().replace("-", "");
            }
            requestWrapper.addHeader(SystemInfo.REQUEST_ID, requestId);

            // String requestId = UUID.randomUUID().toString().replace("-", "");
            //使用slf4j的MDC添加日志的自定义参数
            MDC.put(SystemInfo.REQUEST_ID, requestId);
            logger.info("######################################## [{}:{}]", httpServletRequest.getMethod(), httpServletRequest.getRequestURI());

            // filterChain.doFilter(httpServletRequest, httpServletResponse);
            // 注意这里替换成包装类
            filterChain.doFilter(requestWrapper, responseWrapper);


            // 测试发现不能使用包装类
            ServletOutputStream outputStream = httpServletResponse.getOutputStream();
            // 解决使用包装类后返回有问题
            byte[] content = responseWrapper.getResponseBody();
            httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            // 注意重新设置数据长度
            httpServletResponse.setContentLength(content.length);
            outputStream.write(content);
            // 刷新数据
            outputStream.flush();
            outputStream.close();

            String spendTime = (System.currentTimeMillis() - start) + "ms";
            logger.info("######################################## spendTime : {} \n\n", spendTime);
        } finally {
            MDC.clear();
        }

    }
}
